package ca.bcit.comp3910.access;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.sql.DataSource;

import ca.bcit.comp3910.model.TimesheetRow;

@ApplicationScoped
@Named
/**
 * CRUD for Timesheet
 * 
 * @author Ivy Cheung, Stacy Mitchell
 * @version 2.0
 *
 */
public class TimesheetManager {
	/**
	 * Datasource
	 */
    @Resource(mappedName = "java:jboss/datasources/assignment")
    private DataSource dataSource;
	/**
     * Inject timesheet bean
     */
    @Inject
    TimesheetRow row;
    /**
     * Inject employeemanager bean
     */
    @Inject
    EmployeeManager em;    
    /**
     * Arraylist of timesheet row
     */
    private ArrayList<TimesheetRow> tsrowList = new ArrayList<TimesheetRow>();
	/**
	 * Map of timesheet
	 * key : pair - date of the week : arraylist of timesheetrow
	 */
	private Map<String, ArrayList<TimesheetRow>> tsMap = new TreeMap<String, ArrayList<TimesheetRow>>();
    /**
     * User select which week to view
     */
    private String weektoView;
    /**
     * Week Ending of timesheet
     */
    private String weekDate;
    /**
     * Week num
     */
    private int weekNum;
    /**
     * If you are viewing timesheet or not (modify)
     */
    private boolean viewTS;
    /**
     * Boolean for checking if there is an error in the row
     */
    private boolean errorRow = false;

    /**
     * Save current timesheet and stored into the database
     * 
     * @param temp arraylist of timesheetrow
     */
    public void saveRow(ArrayList<TimesheetRow> temp) {
    	setErrorRow(false);
    	int empID = em.getEmployee().getEmpID();
    	PreparedStatement stmt = null;
        Connection connection = null;
        try {
        	connection = dataSource.getConnection();
        	stmt = connection.prepareStatement("DELETE FROM timesheet WHERE EmployeeID = ? AND WeekDate = ?"); // edit
        	stmt.setInt(1, empID);
        	stmt.setString(2, getWeekDate());
        	stmt.executeUpdate();
            try {
            	for (TimesheetRow tempList : temp) {
            		if(tempList.getProjectName() == null || tempList.getwP() == "") {
            			continue;
            		}
            		stmt = connection.prepareStatement("INSERT INTO timesheet VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            		stmt.setInt(1, empID);
            		stmt.setString(2, getWeekDate());
            		stmt.setInt(3, tempList.getProjectName());
            		stmt.setString(4, tempList.getwP());
            		stmt.setDouble(5, tempList.getSat());
            		stmt.setDouble(6, tempList.getSun());
            		stmt.setDouble(7, tempList.getMon());
            		stmt.setDouble(8, tempList.getTue());
            		stmt.setDouble(9, tempList.getWed());
            		stmt.setDouble(10, tempList.getThu());
            		stmt.setDouble(11, tempList.getFri());
            		stmt.setString(12, tempList.getNotes());
            		stmt.executeUpdate();
            	}
            } finally {
            	if (stmt != null) {
            		stmt.close();
            	}
            }
        } catch (SQLException e) {
        	setErrorRow(true);
			e.printStackTrace();
		} finally {
        	if (connection != null) {
        		try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
        	}
        }
    }
    
    /**
     * Every time a user logs in, this gets called to retrieve
     * timesheet data from the database.
     * Called from onCreate()
     */
    public void loadTimesheet() {
    	tsMap.clear();
    	int empID = em.getEmployee().getEmpID();
    	PreparedStatement stmt = null;
        Connection connection = null;
        try {
        	connection = dataSource.getConnection();
        	stmt = connection.prepareStatement("SELECT * FROM timesheet WHERE EmployeeID = ?");
        	stmt.setInt(1, empID);
            try {
            	ResultSet rs = stmt.executeQuery();
            	while (rs.next()) {
            		String weekDate = rs.getString("WeekDate");
            		if (!tsMap.containsKey(weekDate)) {
            			tsMap.put(weekDate, new ArrayList<TimesheetRow>());
            		}
            		Integer projectName = rs.getInt("Project");
            		String wP = rs.getString("WP");
            		double sat = rs.getDouble("Sat");
            		double sun = rs.getDouble("Sun");
            		double mon = rs.getDouble("Mon");
            		double tue = rs.getDouble("Tue");
            		double wed = rs.getDouble("Wed");
            		double thu = rs.getDouble("Thu");
            		double fri = rs.getDouble("Fri");
            		String notes = rs.getString("Notes");
                    TimesheetRow tsr = new TimesheetRow(projectName, wP, sat, sun, mon, tue, wed, thu, fri, notes);
                    tsMap.get(weekDate).add(tsr);
            	}
            } finally {
            	if (stmt != null) {
            		stmt.close();
            	}
            }
        } catch (SQLException e) {
			e.printStackTrace();
		} finally {
        	if (connection != null) {
        		try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
        	}
        }
    }
    
    /**
     * Gets called when user logs in.
     * Sets up timesheet to view if current week is not in the timesheet map
     * and modify if current week is and adds 5 new rows.
     * @param empID employee ID
     */
    public void onCreate(int empID) {
    		em.setEmployee(empID);
    		loadTimesheet();
        if (!tsMap.containsKey(getWeekDate())) {
            ArrayList<TimesheetRow> perRow = new ArrayList<TimesheetRow>();
            perRow.add(new TimesheetRow());
            perRow.add(new TimesheetRow());
            perRow.add(new TimesheetRow());
            perRow.add(new TimesheetRow());
            perRow.add(new TimesheetRow());
        	tsMap.put(getWeekDate(), perRow);
        }
        else {
        	tsMap.get(getWeekDate()).add(new TimesheetRow());
        	tsMap.get(getWeekDate()).add(new TimesheetRow());
        	tsMap.get(getWeekDate()).add(new TimesheetRow());
        	tsMap.get(getWeekDate()).add(new TimesheetRow());
        	tsMap.get(getWeekDate()).add(new TimesheetRow());
        }
    }
    
    /**
     * Get all data for the selected timesheet
     * by grabbing values from the database
     * 
     * @return array list of timesheet row
     */
    public ArrayList<TimesheetRow> getTsrowList() {
    	if (!isViewTS()) {
        	tsrowList = tsMap.get(getWeekDate());
    	}
    	else {
    		tsrowList = tsMap.get(getWeektoView());
    	}
		return tsrowList;
	}
    
    /**
     * Method for view timesheet button
     * Sets view timesheet flag to true
     */
    public void viewTimesheet() {
    	setViewTS(true);
    }

    /**
     * Get all Timesheets week numbers for an employee
     * by grabbing the values from the database and storing them into the bean
     * 
     * @return array list of week numbers
     */
    public ArrayList<String> getTimesheetWeeks() {
        ArrayList<String> temp = new ArrayList<String>();
        for (Entry<String, ArrayList<TimesheetRow>> entry : tsMap.entrySet()) {
            temp.add(entry.getKey());
        }
        return temp;
    }
       
    /**
     * Get current timesheet's week ending date depending on current week or previous
     * timesheet's date.
     * 
     * @return string of week ending date
     */
    public String getWeekDate() {
    	if (isViewTS() == false) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        	GregorianCalendar calendar = new GregorianCalendar(); 
        	calendar.setTime(new Date());
        	calendar.set(GregorianCalendar.WEEK_OF_YEAR, getWeekNum());
        	calendar.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.FRIDAY);
            weekDate = df.format(calendar.getTime());
    	}
    	else {
    		weekDate = getWeektoView();
    	}
    	return weekDate;
    }
    
    /**
     * Gets week number of the timesheet depending on the current week
     * or previous timesheet's via calculating it from week date
     * @return week number
     */
    @SuppressWarnings("deprecation")
	public int getWeekNum() {
    	if (isViewTS() == false) {
	    	Calendar cal = Calendar.getInstance();
	        weekNum = cal.get(Calendar.WEEK_OF_YEAR);
    	}
    	else {
    		String week = getWeekDate();
    		System.out.println(week);
    		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        	GregorianCalendar calendar = new GregorianCalendar();
        	calendar.setFirstDayOfWeek(Calendar.FRIDAY);
        	Date date = new Date();
			try {
				date = df.parse(week);
				calendar.set(date.getYear(), date.getMonth(), date.getDate());
			} catch (ParseException e) {
				e.printStackTrace();
			}
        	weekNum = calendar.get(Calendar.WEEK_OF_YEAR);
        	weekNum--; // has to reduce it by a week, it calculates one extra week
    	}
        return weekNum;
    }
	
    /**
     * Check to see that the combination of Project and WP are unique
     * 
     * @param project title
     * @param wp string
     */
    public boolean checkValidRow(Integer project, String wp, int count) {
    	int validCount = 0;
    	for (int i = 0; i < tsrowList.size(); i++) {
    		if(tsrowList.get(i).getProjectName() != null) {
    			validCount++;
    		}
    	}
    	System.out.println(count);
    	System.out.println(validCount);
    	for (int i = count; i < validCount - 1; i++) {
    		if (tsrowList.get(i).getProjectName() == null || tsrowList.get(i).getwP() == null) {
    			return true;
    		}
    		System.out.println(project + " " + wp + " "+ tsrowList.get(i).getProjectName() + " " + tsrowList.get(i).getwP() );
    		if (tsrowList.get(i).getProjectName() == project) {
    			if (tsrowList.get(i).getwP().equals(wp)) {
    				setErrorRow(true);
    				return false;
    			}
    		}
    	}
        return true;
    }
    
    /**
     * Getters and setters
     */
    public boolean isViewTS() { return viewTS; }
	public void setViewTS(boolean viewTS) {	this.viewTS = viewTS; }

    public void setWeektoView(String weekNum){	this.weektoView = weekNum; }
	public String getWeektoView() { return weektoView; }
	
	public boolean isErrorRow() { return errorRow; }
	public void setErrorRow(boolean errorRow) {	this.errorRow = errorRow;	}
}
